home *** CD-ROM | disk | FTP | other *** search
/ MacFormat 1999 Spring / macformat-077.iso / Shareware Plus / Development / SpriteWorld 2.2 / SpriteWorld files / Utils / Brian's Extensions / SWLightingSquares.c < prev    next >
Encoding:
Text File  |  1999-01-14  |  27.7 KB  |  790 lines  |  [TEXT/CWIE]

  1. /*  -----------------------------------------------------------------------------------
  2.     -----------------------------------------------------------------------------------
  3.     SWLightingSquares.c
  4.     
  5.     by Brian Roddy
  6.     
  7.     5/20/97
  8.  
  9.     
  10.     ** N.B. These functions are still experimental.  They work fine, but the public API
  11.        needs work to achieve better effects and uses.
  12.  
  13.  
  14.     These routines are for an alternative style of getting lighting effects.  It's
  15.     main function is a Screen Blitting procedures that takes the offscreen work area
  16.     and colors it as it copies it on screen.  Thus the parts copied on screen can 
  17.     be made darker or lighter or a little reddish, etc.  
  18.     
  19.     To support a feeling of lights, we divide the screen into a map of tiny squares 
  20.     and associate a color and a level with each square.  As we blit onto the screen,
  21.     we use this map to color the image.  The result is that the screen image looks
  22.     nicely colorized.  Imagine each square having a colored gel placed over top of 
  23.     it.
  24.     
  25.     The smaller the squares in our map, the finer the grain of lighting but the greater
  26.     the overhead.  More space and speed are required.  We also provide routines for setting 
  27.     and managing this lighting map, including setting light levels and combining 
  28.     lights (so blue lights and yellow lights will become greenish lights as they overlap).
  29.  
  30.     These functions make use of the translucency table functions found in 
  31.     "SWTranslucentBlitters.c" and therefore that file needs to be present for this to
  32.     work.
  33.  
  34.     Use SWInitializeLightingSquares(spriteWorldPtr, 8); to initialize the use of squares.
  35.     8 in this case is the size of the squares in pixels.  
  36.     
  37.     Use:
  38.         SWSetLightingSquare(spriteWorldPtr, col, row, 
  39.                              color, opacity,
  40.                              relativeP, makeDirtyP);
  41.     to set a cell's value.  Opacity is the translucency levels (as in the translucent blitters).
  42.     relativeP is a boolean specifying whether to set the color and level directly or to blend
  43.     it together with what is already in the cell.   makeDirtyP forces sprite world to redraw
  44.     that cell on the screen during the next draw loop.
  45.     
  46.     Use:
  47.         SWLightUpArea (spriteWorldPtr, col, row, 
  48.                         color,  level
  49.                         bigLightP);
  50.     to light up an area around a cell.  This is good for spotlights.  bigLightP makes the light
  51.     really big.  Note that this just calls     SWSetLightingSquare repeatedly.        
  52.  
  53.     SWDarkenLightingSquares (spriteWorldPtr); will blend black into every square in the
  54.     grid to darken everything.  This is a good example of how to achieve a lighting effect
  55.     with these squares.
  56.     
  57.     Use SWExitLightingSquares (); to free up the tables when quitting.  
  58.  
  59.     The Lit Breakout Demo is an example of how to use these functions in an app.
  60.  
  61.  
  62.     -------------------------------------------------------------------------------------
  63.     Implementation Notes:
  64.  
  65.     The engine for all of this is the code for blitting Tinted Rects in 8 bit or in 16 bit 
  66.     mode.  There are straight C versions as well as versions that use optimize PowerPC 
  67.     assembly. 
  68.          
  69.     This source code is available for free use.
  70.     ----------------------------------------------------------------------------------- 
  71.     ----------------------------------------------------------------------------------- */
  72.  
  73. ///--------------------------------------------------------------------------------------
  74. // Includes
  75. ///--------------------------------------------------------------------------------------
  76.  
  77. #include "SWTranslucentBlitters.h"
  78. #include "SWLightingSquares.h"
  79. #include <SWGameUtils.h>
  80.  
  81. unsigned long *gLitSquareColorTable;
  82. unsigned long *gLitSquareLevelTable;
  83. int gLightingSquareRows, gLightingSquareColumns;
  84. int SWLitSquareSize    = 8;
  85.  
  86. unsigned long gBlackColor;
  87.  
  88. #pragma mark ----------- Public API -------------
  89. SW_FUNC OSErr     SWInitializeLightingSquares (SpriteWorldPtr spriteWorldP, 
  90.                                             int squareSize) {
  91.     long                arraySize;
  92.     OSErr                err = noErr;
  93.     
  94.     SWLitSquareSize = squareSize;
  95.     gLightingSquareColumns = ((spriteWorldP->windRect.right - spriteWorldP->windRect.left) / SWLitSquareSize) + 1;
  96.     gLightingSquareRows = ((spriteWorldP->windRect.bottom - spriteWorldP->windRect.top) / SWLitSquareSize) + 1;
  97.     
  98.     SWExitLightingSquares ();
  99.     
  100.     if (err == noErr) {
  101.         if (spriteWorldP->pixelDepth == 8) {
  102.             SWSetSpriteWorldScreenDrawProc(spriteWorldP, BlitPixie8BitLitRectDrawProc);
  103.             CreateCLUTTable();
  104.             gBlackColor = ColorToIndex(0,0,0);
  105.         } else if (spriteWorldP->pixelDepth == 16) {
  106.             SWSetSpriteWorldScreenDrawProc(spriteWorldP, BlitPixie16BitLitRectDrawProc);
  107.             gBlackColor = 0x0000;
  108.         
  109.         }
  110.         else
  111.             err = kWrongDepthErr;
  112.     }
  113.  
  114.     if (err == noErr) {
  115.         arraySize = gLightingSquareColumns * gLightingSquareRows * sizeof(unsigned long);
  116.         gLitSquareColorTable = (unsigned long *)NewPtr(arraySize);
  117.         err = MemError();
  118.     }
  119.     
  120.     if (err == noErr) {
  121.         arraySize = gLightingSquareColumns * gLightingSquareRows * sizeof(unsigned long);
  122.         gLitSquareLevelTable = (unsigned long *)NewPtr(arraySize);
  123.         err = MemError();
  124.     }
  125.     
  126.     return err;
  127. }
  128.  
  129. SW_FUNC void     SWExitLightingSquares ()
  130. {
  131.     // Only do this if we've created a table.
  132.     if (gLitSquareColorTable != NULL) DisposePtr((Ptr)gLitSquareColorTable);
  133.     if (gLitSquareLevelTable != NULL) DisposePtr((Ptr)gLitSquareLevelTable);
  134. }
  135.  
  136.  
  137.  
  138. ///--------------------------------------------------------------------------------------
  139. ///--------------------------------------------------------------------------------------
  140. /// Table Management Functions
  141. ///--------------------------------------------------------------------------------------
  142. ///--------------------------------------------------------------------------------------
  143.  
  144. SW_FUNC void SWSetLightingSquare(SpriteWorldPtr swp, int col, int row, 
  145.                          unsigned long color, unsigned long level,
  146.                          Boolean relative, Boolean makeDirty) {
  147.     long index, curColor, curLevel, newColor, newLevel;
  148.     Rect changedRect;
  149.     
  150.     // Bounds Checking
  151.     if (! ((row < 0) || 
  152.            (col < 0) || 
  153.            (row >= gLightingSquareRows) ||
  154.            (col >= gLightingSquareColumns))) {
  155.         
  156.         int maxLevel;
  157.         if (swp->pixelDepth == 8) 
  158.             maxLevel = gNumberOf8BitTranslucencyLevels;
  159.         else
  160.             maxLevel = 32;
  161.         if (level < 0) level = 0;
  162.         if (level >= maxLevel) level = (maxLevel - 1);
  163.         
  164.         // Compute the data structure
  165.         index = ((row * gLightingSquareColumns) + col);
  166.         curColor = gLitSquareColorTable[index];
  167.         curLevel = gLitSquareLevelTable[index];
  168.         
  169.         if (relative) {
  170.             if (swp->pixelDepth == 8) { 
  171.                 newColor = Blend8BitPixels(level, curColor, color);
  172.             } else {
  173.                 newColor = Blend16BitPixels(level, curColor, color);
  174.             }
  175.             
  176.             if (newColor == curColor) 
  177.                 newColor = color;
  178.  
  179.             newLevel = (curLevel + level) / 2;
  180.             if (newLevel == curLevel) 
  181.                 newLevel = level;
  182.                 
  183.         } else {
  184.             newColor = color;
  185.             newLevel = level;
  186.         }
  187.             
  188.         // And if the value is different
  189.         if ((curColor != newColor) ||
  190.             (curLevel != newLevel)) {
  191.  
  192.             // Update the data structure
  193.             gLitSquareColorTable[index] = newColor;
  194.             gLitSquareLevelTable[index] = newLevel;
  195.             
  196.             if (makeDirty) {
  197.                 // And tell spriteworld that the square is dirty
  198.                 changedRect.top = row * SWLitSquareSize;
  199.                 changedRect.bottom = ((row + 1) * SWLitSquareSize);
  200.                 changedRect.left = col * SWLitSquareSize;
  201.                 changedRect.right = ((col + 1) * SWLitSquareSize);
  202.                 SWFlagRectAsChanged(swp, &changedRect);
  203.             }
  204.         }
  205.     }
  206. }
  207.  
  208. ///--------------------------------------------------------------------------------------
  209. ///---- SWDarkenLightingSquares.
  210. ///
  211. /// A utility function to do light fading over time.
  212.  
  213. SW_FUNC void SWDarkenLightingSquares (SpriteWorldPtr swp)
  214. {
  215.     int row, col, index = 0;
  216.     int maxLevel;
  217.     
  218.     if (swp->pixelDepth == 8)
  219.         maxLevel = gNumberOf8BitTranslucencyLevels - 1;
  220.     else
  221.         maxLevel = 30;
  222.     
  223.     for (row = 0; row < gLightingSquareRows; row++)
  224.         for (col = 0; col < gLightingSquareColumns; col++) {
  225.             if ((gLitSquareColorTable[index] != gBlackColor) ||
  226.                 (gLitSquareLevelTable[index] != maxLevel)) {
  227.                 int index = ((row * gLightingSquareColumns) + col);
  228.                 int curLevel = gLitSquareLevelTable[index];
  229.  
  230.                 SWSetLightingSquare(swp, col, row, gBlackColor, maxLevel, (curLevel != maxLevel), true);
  231.             }
  232.             index++;
  233.         }
  234. }
  235.  
  236.  
  237. ///--------------------------------------------------------------------------------------
  238. ///--------------------------------------------------------------------------------------
  239.  
  240. SW_FUNC void SWLightUpArea (
  241.     SpriteWorldPtr swp, 
  242.     int col, 
  243.     int row, 
  244.     unsigned long lightColor, 
  245.     int lightLevel, 
  246.     Boolean BigLight) {
  247.  
  248.     // Light up the tiles around the sprite.  Light up the center sprite and
  249.     // adjacent ones really bright, Light up the four diagonally adjacent ones
  250.     // fairly bright. 
  251.     
  252.     // Calculate the light levels
  253.     int lightLevelBorder = lightLevel;
  254.     int lightLevelMiddle = lightLevelBorder; // + RandomNumber(2);
  255.     
  256.     Boolean blendIt = true;
  257.     
  258.     // and light them up
  259.     SWSetLightingSquare(swp, col - 1, row - 1, lightColor, lightLevelBorder, blendIt, true);
  260.     SWSetLightingSquare(swp, col    , row - 1, lightColor, lightLevelMiddle, blendIt, true);
  261.     SWSetLightingSquare(swp, col + 1, row - 1, lightColor, lightLevelBorder, blendIt, true);
  262.     SWSetLightingSquare(swp, col - 1, row    , lightColor, lightLevelMiddle, blendIt, true);
  263.     SWSetLightingSquare(swp, col    , row    , lightColor, lightLevelMiddle, blendIt, true);
  264.     SWSetLightingSquare(swp, col + 1, row    , lightColor, lightLevelMiddle, blendIt, true);
  265.     SWSetLightingSquare(swp, col - 1, row + 1, lightColor, lightLevelBorder, blendIt, true);
  266.     SWSetLightingSquare(swp, col    , row + 1, lightColor, lightLevelMiddle, blendIt, true);
  267.     SWSetLightingSquare(swp, col + 1, row + 1, lightColor, lightLevelBorder, blendIt, true);
  268.  
  269.     if (BigLight)
  270.     {   /// If BigLight is true then we make a really big light that 
  271.         /// lights up a 5x5 area of tiles rather than 3x3
  272.         int lightLevelEdgeCorner = lightLevelBorder + 2;
  273.         int lightLevelEdgeNearCorner = lightLevelBorder + 1;
  274.         int lightLevelEdge = lightLevelBorder + 1;
  275.  
  276.         SWSetLightingSquare(swp, col - 2, row - 2, lightColor, lightLevelEdgeCorner, blendIt, true);
  277.         SWSetLightingSquare(swp, col + 2, row - 2, lightColor, lightLevelEdgeCorner, blendIt, true);
  278.         SWSetLightingSquare(swp, col - 2, row + 2, lightColor, lightLevelEdgeCorner, blendIt, true);
  279.         SWSetLightingSquare(swp, col + 2, row + 2, lightColor, lightLevelEdgeCorner, blendIt, true);
  280.         SWSetLightingSquare(swp, col - 1, row - 2, lightColor, lightLevelEdgeNearCorner, blendIt, true);
  281.         SWSetLightingSquare(swp, col    , row - 2, lightColor, lightLevelEdge, blendIt, true);
  282.         SWSetLightingSquare(swp, col + 1, row - 2, lightColor, lightLevelEdgeNearCorner, blendIt, true);
  283.         SWSetLightingSquare(swp, col - 1, row + 2, lightColor, lightLevelEdgeNearCorner, blendIt, true);
  284.         SWSetLightingSquare(swp, col    , row + 2, lightColor, lightLevelEdge, blendIt, true);
  285.         SWSetLightingSquare(swp, col + 1, row + 2, lightColor, lightLevelEdgeNearCorner, blendIt, true);
  286.         SWSetLightingSquare(swp, col - 2, row - 1, lightColor, lightLevelEdgeNearCorner, blendIt, true);
  287.         SWSetLightingSquare(swp, col - 2, row    , lightColor, lightLevelEdge, blendIt, true);
  288.         SWSetLightingSquare(swp, col - 2, row + 1, lightColor, lightLevelEdgeNearCorner, blendIt, true);
  289.         SWSetLightingSquare(swp, col + 2, row - 1, lightColor, lightLevelEdgeNearCorner, blendIt, true);
  290.         SWSetLightingSquare(swp, col + 2, row    , lightColor, lightLevelEdge, blendIt, true);
  291.         SWSetLightingSquare(swp, col + 2, row + 1, lightColor, lightLevelEdgeNearCorner, blendIt, true);
  292.     }
  293.     
  294. }
  295.  
  296.  
  297. ///--------------------------------------------------------------------------------------
  298. ///--------------------------------------------------------------------------------------
  299. /// The Blitting Functions
  300. ///--------------------------------------------------------------------------------------
  301. ///--------------------------------------------------------------------------------------
  302.  
  303. extern SInt8                 gSWmmuMode;
  304.  
  305. #pragma mark ----------- 8 Bit Screen Draw Function -------------
  306. ///--------------------------------------------------------------------------------------
  307. //        BlitPixie8BitRectDrawProc
  308. ///--------------------------------------------------------------------------------------
  309.  
  310. SW_FUNC void BlitPixie8BitLitRectDrawProc(
  311.     FramePtr srcFrameP,
  312.     FramePtr dstFrameP,
  313.     Rect* srcRect,
  314.     Rect* dstRect
  315.     )
  316. {
  317.     Rect                     srcBlitRect = *srcRect;
  318.     Rect                     dstBlitRect = *dstRect;
  319.     unsigned long             numBytesPerRow;
  320.     register unsigned char     *tableAtLevelAndIndex;
  321.     int                     startRow, endRow, startCol, endCol;
  322.     int                     row, col, index;
  323.     Rect                     curSrcBlitRect, curDstBlitRect;
  324.     
  325.     SW_ASSERT(srcFrameP->isFrameLocked && dstFrameP->isFrameLocked);
  326.     SW_ASSERT((*srcFrameP->framePort->portPixMap)->pixelSize == 8);
  327.     SW_ASSERT((*dstFrameP->framePort->portPixMap)->pixelSize == 8);
  328.  
  329.     BP_CLIP_RECT(dstFrameP->frameRect, srcBlitRect, dstBlitRect);    
  330.     START_32_BIT_MODE
  331.     
  332.     startRow = dstBlitRect.top / SWLitSquareSize;
  333.     startCol = dstBlitRect.left / SWLitSquareSize;
  334.     endRow = (dstBlitRect.bottom / SWLitSquareSize) + 1 ;
  335.     endCol = (dstBlitRect.right / SWLitSquareSize) + 1;
  336.     
  337.     for (row = startRow; row <= endRow; row++) {
  338.         for (col = startCol; col <= endCol; col++) {
  339.             index = ((row * gLightingSquareColumns) + col);
  340.             tableAtLevelAndIndex = &g8BitTranslucencyTable[(gLitSquareLevelTable[index] << 16) | (gLitSquareColorTable[index] << 8)];
  341.             
  342.             curSrcBlitRect.top = row * SWLitSquareSize;
  343.             curSrcBlitRect.bottom = curSrcBlitRect.top + SWLitSquareSize;
  344.             curSrcBlitRect.left = col * SWLitSquareSize;
  345.             curSrcBlitRect.right = curSrcBlitRect.left + SWLitSquareSize;
  346.             curDstBlitRect.top = row * SWLitSquareSize;
  347.             curDstBlitRect.bottom = curDstBlitRect.top + SWLitSquareSize;
  348.             curDstBlitRect.left = col * SWLitSquareSize;
  349.             curDstBlitRect.right = curDstBlitRect.left + SWLitSquareSize;
  350.             
  351.             SectRect(&dstBlitRect, &curDstBlitRect, &curDstBlitRect);
  352.             SectRect(&srcBlitRect, &curSrcBlitRect, &curSrcBlitRect);
  353.             
  354.                 // calculate the number of bytes in each row to be copied
  355.             numBytesPerRow = (curDstBlitRect.right - curDstBlitRect.left);
  356.  
  357.             BlitPixieLit8Bit(
  358.                     // calculate the address of the first byte of the source
  359.                 (PixelChunkPtr)(srcFrameP->frameBaseAddr + 
  360.                     (srcFrameP->scanLinePtrArray[curSrcBlitRect.top - srcFrameP->frameRect.top]) + 
  361.                     curSrcBlitRect.left),
  362.  
  363.                     // calculate the address of the first byte of the destination
  364.                 (PixelChunkPtr)(dstFrameP->frameBaseAddr + 
  365.                     (dstFrameP->scanLinePtrArray[curDstBlitRect.top]) + curDstBlitRect.left),
  366.  
  367.                     // calculate the number of rows to blit
  368.                 curDstBlitRect.bottom - curDstBlitRect.top,
  369.  
  370.                     // number of bytes in a row (also the number of pixels to be copied)
  371.                 numBytesPerRow,
  372.  
  373.                 srcFrameP->frameRowBytes,
  374.                 dstFrameP->frameRowBytes,
  375.                 tableAtLevelAndIndex
  376.                 );
  377.         }
  378.     }
  379.     
  380.     END_32_BIT_MODE
  381. }
  382.  
  383.  
  384. ///--------------------------------------------------------------------------------------
  385. //        LightingConvertChar
  386. ///--------------------------------------------------------------------------------------
  387.  
  388. SW_FUNC unsigned char SWInline LightingConvertChar (
  389.     register unsigned char srcPixel, 
  390.     register unsigned char *tableAtLevelAndIndex) {
  391.     
  392.     // Easy, just the pixel in the table
  393.     return tableAtLevelAndIndex[srcPixel];
  394. }
  395.  
  396.  
  397. ///--------------------------------------------------------------------------------------
  398. //        LightingConvertShort
  399. ///--------------------------------------------------------------------------------------
  400.  
  401. SW_FUNC unsigned short  LightingConvertShort (
  402.     register unsigned short srcPixel, 
  403.     register unsigned char *tableAtLevelAndIndex) {
  404.     
  405.     register unsigned long colorValue;
  406.     register unsigned long result = 0L;
  407.     
  408.     colorValue = tableAtLevelAndIndex[srcPixel >> 8];
  409.     result = colorValue << 8;
  410.     colorValue = tableAtLevelAndIndex[(srcPixel  & 0x00FF)];
  411.     result = colorValue | result;
  412.     return result;
  413. }
  414.  
  415. #if USE_PPC_ASSEMBLY && __MWERKS__ >= 0x1800    // Only compiles under CW Pro
  416.  
  417. ///--------------------------------------------------------------------------------------
  418. //        LightingConvertLong
  419. ///--------------------------------------------------------------------------------------
  420.  
  421. SW_FUNC unsigned long  LightingConvertLong (
  422.     register unsigned long srcPixel, 
  423.     register unsigned char *tableAtLevelAndIndex) {
  424.     
  425.     register unsigned long colorValue;
  426.     register unsigned long result;
  427.     
  428.     colorValue = tableAtLevelAndIndex[srcPixel >> 24];    // look up the colored pixel
  429.     result = colorValue << 24;                            // and shift it back into place as our high end pixel
  430.     colorValue = tableAtLevelAndIndex[((srcPixel >> 16)  & 0x000000FF)];
  431.     __rlwimi(    result, colorValue, 16, 8, 15    );
  432.     colorValue = tableAtLevelAndIndex[((srcPixel >> 8)  & 0x000000FF)];
  433.     __rlwimi(    result, colorValue, 8, 16, 23    );
  434.     colorValue = tableAtLevelAndIndex[(srcPixel  & 0x000000FF)];
  435.     __rlwimi(    result, colorValue, 0, 24, 31    );
  436.         
  437.     // return the four pixels we've computed
  438.     return result;    
  439. }
  440.  
  441. #else /* USE_PPC_ASSEMBLY && __MWERKS__ >= 0x1800 */
  442.  
  443. ///--------------------------------------------------------------------------------------
  444. //        LightingConvertLong
  445. ///--------------------------------------------------------------------------------------
  446.  
  447. SW_FUNC unsigned long SWInline LightingConvertLong (
  448.     register unsigned long srcPixel, 
  449.     register unsigned char *tableAtLevelAndIndex) {
  450.     
  451.     register unsigned long colorValue;
  452.     register unsigned long result = 0L;
  453.     
  454.     colorValue = tableAtLevelAndIndex[srcPixel >> 24];    // look up the colored pixel
  455.     result = colorValue << 24;                            // and shift it back into place as our high end pixel
  456.     colorValue = tableAtLevelAndIndex[((srcPixel >> 16)  & 0x000000FF)];
  457.     result = (colorValue << 16) | result;
  458.     colorValue = tableAtLevelAndIndex[((srcPixel >> 8)  & 0x000000FF)];
  459.     result = (colorValue << 8) | result;
  460.     colorValue = tableAtLevelAndIndex[(srcPixel  & 0x000000FF)];
  461.     result = colorValue | result;
  462.         
  463.     // return the four pixels we've computed
  464.     return result;    
  465. }
  466.  
  467. #endif /* USE_PPC_ASSEMBLY */
  468.  
  469. ///--------------------------------------------------------------------------------------
  470. //        BlitPixieLit8Bit
  471. ///--------------------------------------------------------------------------------------
  472.  
  473.  
  474. SW_FUNC void BlitPixieLit8Bit(
  475.     PixelChunkPtr srcPixelP,
  476.     PixelChunkPtr dstPixelP,
  477.     register unsigned long rowsToCopy,
  478.     register unsigned long numBytesPerRow,
  479.     register unsigned long srcOffset,
  480.     register unsigned long dstOffset,
  481.     register unsigned char *tableAtLevelAndIndex)
  482. {
  483.     register long index;
  484.     register PixelChunkPtr startSrcPixelP;
  485.     register PixelChunkPtr startDstPixelP;
  486.     
  487.         
  488.     startSrcPixelP = srcPixelP;
  489.     startDstPixelP = dstPixelP;
  490.  
  491.     while (rowsToCopy--)
  492.     {
  493.         register fourblits = (numBytesPerRow >> 2);
  494.         
  495.         srcPixelP = startSrcPixelP;
  496.         dstPixelP = startDstPixelP;
  497.         
  498.         for (index = 0; index < fourblits; index++) {
  499.             dstPixelP[index] = LightingConvertLong(srcPixelP[index], tableAtLevelAndIndex);
  500.         }
  501.  
  502.         srcPixelP += fourblits;
  503.         dstPixelP += fourblits;
  504.         
  505. #ifdef MWERKS        
  506.         if (numBytesPerRow & 0x2)
  507.             *((unsigned short *) dstPixelP)++ = LightingConvertShort(*((unsigned short *) srcPixelP)++, tableAtLevelAndIndex);
  508.         if (numBytesPerRow & 0x1)
  509.             *((unsigned char *) dstPixelP)++ = LightingConvertChar(*((unsigned char *) srcPixelP)++, tableAtLevelAndIndex);
  510. #else        
  511.         if (numBytesPerRow & 0x2)
  512.         {
  513.                 // Work around Think C's inability to do simple typecasting - Vern
  514.             *(unsigned short *)dstPixelP = LightingConvertShort(*(unsigned short *)srcPixelP, tableAtLevelAndIndex);
  515.             srcPixelP = (PixelChunkPtr)(((unsigned short *)srcPixelP) + 1);
  516.             dstPixelP = (PixelChunkPtr)(((unsigned short *)dstPixelP) + 1);
  517.         }
  518.         if (numBytesPerRow & 0x1)
  519.         {
  520.             *(unsigned char *)dstPixelP = LightingConvertChar(*(unsigned char *)srcPixelP, tableAtLevelAndIndex);
  521.             srcPixelP = (PixelChunkPtr)(((unsigned char *)srcPixelP) + 1);
  522.             dstPixelP = (PixelChunkPtr)(((unsigned char *)dstPixelP) + 1);
  523.         }
  524. #endif
  525.  
  526.             // bump to next row    
  527. #ifdef MWERKS
  528.         (char *)startSrcPixelP += srcOffset;
  529.         (char *)startDstPixelP += dstOffset;
  530. #else
  531.         startSrcPixelP = (PixelChunkPtr)(((char *)startSrcPixelP) + srcOffset);
  532.         startDstPixelP = (PixelChunkPtr)(((char *)startDstPixelP) + dstOffset);
  533. #endif
  534.     }
  535. }
  536.  
  537. ///--------------------------------------------------------------------------------------
  538. ///--------------------------------------------------------------------------------------
  539. ///--------------------------------------------------------------------------------------
  540. ///--------------------------------------------------------------------------------------
  541. ///--------------------------------------------------------------------------------------
  542. /// 16 Bit Versions
  543.  
  544. #pragma mark ----------- 16 Bit Screen Draw Function -------------
  545. ///--------------------------------------------------------------------------------------
  546. //        BlitPixie16BitRectDrawProc
  547. ///--------------------------------------------------------------------------------------
  548.  
  549. SW_FUNC void BlitPixie16BitLitRectDrawProc(
  550.     FramePtr srcFrameP,
  551.     FramePtr dstFrameP,
  552.     Rect* srcRect,
  553.     Rect* dstRect
  554.     )
  555. {
  556.     Rect                     srcBlitRect = *srcRect;
  557.     Rect                     dstBlitRect = *dstRect;
  558.     unsigned long             numBytesPerRow;
  559.     int                     startRow, endRow, startCol, endCol;
  560.     int                     row, col, index;
  561.     Rect                     curSrcBlitRect, curDstBlitRect;
  562.     
  563.     SW_ASSERT(srcFrameP->isFrameLocked && dstFrameP->isFrameLocked);
  564.     SW_ASSERT((*srcFrameP->framePort->portPixMap)->pixelSize == 16);
  565.     SW_ASSERT((*dstFrameP->framePort->portPixMap)->pixelSize == 16);
  566.  
  567.     BP_CLIP_RECT(dstFrameP->frameRect, srcBlitRect, dstBlitRect);    
  568.     START_32_BIT_MODE
  569.     
  570.     startRow = dstBlitRect.top / SWLitSquareSize;
  571.     startCol = dstBlitRect.left / SWLitSquareSize;
  572.     endRow = (dstBlitRect.bottom / SWLitSquareSize) + 1 ;
  573.     endCol = (dstBlitRect.right / SWLitSquareSize) + 1;
  574.     
  575.     for (row = startRow; row <= endRow; row++) {
  576.         for (col = startCol; col <= endCol; col++) {
  577.             index = ((row * gLightingSquareColumns) + col);
  578.             
  579.             curSrcBlitRect.top = row * SWLitSquareSize;
  580.             curSrcBlitRect.bottom = curSrcBlitRect.top + SWLitSquareSize;
  581.             curSrcBlitRect.left = col * SWLitSquareSize;
  582.             curSrcBlitRect.right = curSrcBlitRect.left + SWLitSquareSize;
  583.             curDstBlitRect.top = row * SWLitSquareSize;
  584.             curDstBlitRect.bottom = curDstBlitRect.top + SWLitSquareSize;
  585.             curDstBlitRect.left = col * SWLitSquareSize;
  586.             curDstBlitRect.right = curDstBlitRect.left + SWLitSquareSize;
  587.             
  588.             SectRect(&dstBlitRect, &curDstBlitRect, &curDstBlitRect);
  589.             SectRect(&srcBlitRect, &curSrcBlitRect, &curSrcBlitRect);
  590.  
  591.             numBytesPerRow = curDstBlitRect.right - curDstBlitRect.left;
  592.  
  593.             if (numBytesPerRow > 0)  // don't draw when the intersection is null...
  594.                 BlitPixieLit16Bit(
  595.                         // calculate the address of the first byte of the source
  596.                     (unsigned short *)(srcFrameP->frameBaseAddr + 
  597.                         (srcFrameP->scanLinePtrArray[curSrcBlitRect.top - srcFrameP->frameRect.top]) + 
  598.                         (curSrcBlitRect.left << 1)),
  599.  
  600.                         // calculate the address of the first byte of the destination
  601.                     (unsigned short *)(dstFrameP->frameBaseAddr + 
  602.                         (dstFrameP->scanLinePtrArray[curDstBlitRect.top]) + 
  603.                         (curDstBlitRect.left << 1)),
  604.  
  605.                         // number of bytes in a row (also the number of pixels to be copied)
  606.                     numBytesPerRow,
  607.                     curDstBlitRect.bottom - curDstBlitRect.top,
  608.  
  609.                     srcFrameP->frameRowBytes,
  610.                     dstFrameP->frameRowBytes,
  611.                     gLitSquareColorTable[index],
  612.                     gLitSquareLevelTable[index]
  613.                     );
  614.         }
  615.     }
  616.     
  617.     END_32_BIT_MODE
  618. }
  619.  
  620.  
  621. #if USE_PPC_ASSEMBLY
  622.  
  623. // Some defines to make this easier to read
  624. #define lookup_offset1 alpha
  625. #define lookup_offset2 r11
  626. #define lookup_offset3 r12
  627. #define tablePointer r13
  628. #define tmp1 r0
  629. #define tmp2 r31
  630. #define tmp3 r30
  631.  
  632. void asm BlitPixieLit16Bit(
  633.     register unsigned short *srcPtr,
  634.     register unsigned short *dstPtr,
  635.     register unsigned long width,
  636.     register unsigned long height,
  637.     register unsigned long srcRowBytes,
  638.     register unsigned long dstRowBytes,
  639.     register unsigned long color,
  640.     register unsigned long alpha)
  641. {
  642.     stw     tmp2,-4(SP)    //store temp vars on the stack 
  643.     stw     tmp3,-8(SP)
  644.     stw     lookup_offset2,-12(SP)
  645.     stw     lookup_offset3,-16(SP)
  646.     stw     tablePointer,-20(SP)
  647.  
  648.     // Load a register with a pointer to our table
  649.     lwz      tablePointer, g16BitTranslucencyTable(RTOC)
  650.     lwz      tablePointer, 0(tablePointer)
  651.     
  652.     // We need to make the rowBytes be rowBytes - width because we are using
  653.     // preincrements when getting and setting the pixels
  654.     add        tmp1, width, width                //adjust for pixels being 2 bytes long
  655.     sub        srcRowBytes,srcRowBytes,tmp1    //calculateoffsets to the next row
  656.     sub        dstRowBytes,dstRowBytes,tmp1
  657.  
  658.     //adjust the pointers so we can use pre-increments
  659.     subi    srcPtr,srcPtr,2
  660.     subi    dstPtr,dstPtr,2
  661.         
  662.     // Set up the offsets into the blending table for each of our R, G, and B lookups
  663.     // by setting the high order five bits to the alpha color
  664.     // Note that these high order bits never get changed as we
  665.     // work on our pixels, so the alpha (translucency level)
  666.     // stays the same
  667.     rlwinm    lookup_offset3,alpha,10,17,21 
  668.     mr        lookup_offset2,lookup_offset3
  669.     mr        lookup_offset1,lookup_offset3
  670.     
  671.     rlwimi    lookup_offset3, color, 5, 22, 26        //blue channel source
  672.     rlwimi    lookup_offset2, color, 0, 22, 26        //green channel source
  673.     rlwimi    lookup_offset1, color, 27, 22, 26    //red channel source
  674.         
  675.     
  676. @yloop
  677.     mtctr     width                                    //set the ctr to so we copy do WIDTH number of pixels
  678.  
  679.         @xloop
  680.             lhzu    tmp1,2(srcPtr)                    //load the source and destination colour
  681.             
  682.             rlwimi    lookup_offset3,tmp1,0,27,31        //blue channel destination    
  683.             rlwimi    lookup_offset2,tmp1,27,27,31    //green channel destination
  684.             rlwimi    lookup_offset1,tmp1,22,27,31    //red channel destination
  685.             
  686.             lbzx    tmp3,tablePointer,lookup_offset3    //load blended blue channel
  687.             lbzx    tmp2,tablePointer,lookup_offset2    //load blended green channel
  688.             lbzx    tmp1,tablePointer,lookup_offset1    //load blended red channel
  689.             
  690.             rlwimi    tmp3,tmp2,5,22,26                //insert green channel into result
  691.             rlwimi    tmp3,tmp1,10,17,21                //insert red channel into result
  692.             
  693.             sthu    tmp3,2(dstPtr)                    //store result
  694.  
  695.         @endOfBlitXLoop
  696.             bdnz    @xloop                            // decrement the ctr and see if we're done                
  697.     
  698.     // Now we move the pointers forward to the next row
  699.     add        srcPtr,srcPtr,srcRowBytes
  700.     add        dstPtr,dstPtr,dstRowBytes    
  701.     
  702.     //and if we haven't finished, continue
  703.     subi    height,height,1            
  704.     cmpwi    height,0
  705.     bne        @yloop    
  706.     
  707.     lwz     tmp2,-4(SP)            //clean up, restore registers we've been using
  708.     lwz     tmp3,-8(SP)
  709.     lwz     lookup_offset2,-12(SP)
  710.     lwz     lookup_offset3,-16(SP)
  711.     lwz     tablePointer,-20(SP)
  712.     
  713.     blr
  714.  
  715. }
  716.  
  717. #undef lookup_offset1
  718. #undef lookup_offset2
  719. #undef lookup_offset3
  720. #undef tmp1
  721. #undef tmp2
  722. #undef tmp3
  723. #undef height
  724. #undef width
  725.  
  726. #else /* USE_PPC_ASSEMBLY */
  727.  
  728. // Here is a C version of the above function.  
  729. // it's about 20% slower than the assembly one.
  730.  
  731. // Note: don't declare the args to this function as "register".  If you do, then
  732. // it won't compile properly for the 68K.
  733.  
  734. void BlitPixieLit16Bit (
  735.      unsigned short *srcPtr,
  736.      unsigned short *dstPtr,
  737.      unsigned long width,
  738.      unsigned long height,
  739.      unsigned long srcRowBytes,
  740.      unsigned long dstRowBytes,
  741.      unsigned long color,
  742.      unsigned long alpha) {
  743.     
  744.      int xx, yy;
  745.      unsigned long lookup_offset_blue, lookup_offset_green, lookup_offset_red;
  746.      unsigned long final_red, final_green, final_result;
  747.     short curSource;
  748.  
  749.     srcRowBytes -= width * 2;
  750.     dstRowBytes -= width * 2;
  751.  
  752.     lookup_offset_blue = lookup_offset_green = lookup_offset_red = alpha << 10;
  753.     lookup_offset_blue |= (color << 5) & 0x03E0;
  754.     lookup_offset_green |= color & 0x03E0;
  755.     lookup_offset_red |= (color >> 5) & 0x03E0;
  756.  
  757.     for (yy = 0; yy < height; yy++) {
  758.         for (xx = 0; xx < width; xx++) {
  759.             curSource = *srcPtr++;
  760.             
  761.             lookup_offset_blue &= 0xFFE0;
  762.             lookup_offset_green &= 0xFFE0;
  763.             lookup_offset_red &= 0xFFE0;
  764.  
  765.             lookup_offset_blue |= curSource & 0x001F;
  766.             lookup_offset_green |= (curSource >> 5) & 0x001F;
  767.             lookup_offset_red |= (curSource >> 10) & 0x001F;
  768.  
  769.             final_red = g16BitTranslucencyTable[lookup_offset_red];
  770.             final_green = g16BitTranslucencyTable[lookup_offset_green];
  771.             final_result = g16BitTranslucencyTable[lookup_offset_blue];
  772.  
  773.             final_result |= final_green << 5;
  774.             final_result |= final_red << 10;
  775.  
  776.             *dstPtr++ = final_result;
  777.         }
  778.         
  779. #ifdef MWERKS
  780.         (char *)srcPtr += srcRowBytes;
  781.         (char *)dstPtr += dstRowBytes;
  782. #else
  783.         srcPtr = (unsigned short *)(((char *)srcPtr) + srcRowBytes);
  784.         dstPtr = (unsigned short *)(((char *)dstPtr) + dstRowBytes);
  785. #endif
  786.     }
  787.  
  788. }
  789. #endif /* USE_PPC_ASSEMBLY */
  790.